﻿using System;
using System.Data;
using System.Linq;
using System.Text;

namespace CodeMinder.Output.MotionChart.Entities
{
    [System.ComponentModel.DesignerCategory("NoDesigner")]
    public class DataTable : System.Data.DataTable, IScriptable
    {
        #region IScriptable Members

        public virtual string ToScript()
        {
            var scriptBuilder = new StringBuilder();
            var rows = Rows.Cast<DataRow>();
            var columns = Columns.Cast<DataColumn>();

            scriptBuilder.AppendLine("var data = new google.visualization.DataTable();");
            scriptBuilder.AppendLine(string.Format("data.addRows({0})", rows.Count()));

            const string columnFormat = @"data.addColumn('{0}', '{1}');";
            foreach (var column in columns)
            {
                scriptBuilder.AppendLine(string.Format(columnFormat, GetScriptType(column.DataType), column.ColumnName));
            }

            const string valueFormat = @"data.setValue({0}, {1}, {2});";
            var rowIndex = 0;
            foreach (var row in rows)
            {
                var columnIndex = 0;
                foreach (var column in columns)
                {
                    var type = column.DataType;
                    var value = row.ItemArray[columnIndex];
                    scriptBuilder.AppendLine(string.Format(valueFormat, rowIndex, columnIndex, GetScript(value, type)));
                    columnIndex++;
                }
                rowIndex++;
            }

            return scriptBuilder.ToString();
        }

        #endregion

        #region Script Helper Methods

        private string GetScriptType(Type type)
        {
            if (type == typeof(string))
                return "string";
            if (type == typeof(int))
                return "number";
            if (type == typeof(DateTime))
                return "date";

            throw new ArgumentException("The given Type is not valid for Motion Chart");
        }

        private string GetScript(object o, Type type)
        {
            dynamic value;
            if (type == typeof(string))
                value = (string)o;
            else if (type == typeof(int))
                value = (int)o;
            else if (type == typeof(DateTime))
                value = (DateTime)o;
            else
                throw new ArgumentException("The given Type is not valid for Motion Chart");

            return GetScript(value);
        }

        private string GetScript(string s)
        {
            return "'" + s + "'";
        }

        private string GetScript(int n)
        {
            return n.ToString();
        }

        private string GetScript(DateTime date)
        {
            return string.Format("new Date ({0},{1},{2})", date.Year, date.Month, date.Day);
        }

        #endregion
    }
}
